package main

import (
	"fmt"
	"os"
	"strings"

	"gopkg.in/ini.v1"
)

func main() {
	// 参数校验
	if len(os.Args) < 5 {
		fmt.Println("使用方式: ./命令 ini 配置文件路径 section名 \"k1=v1@@k2=v2\"")
		fmt.Println("示例1 (单行): ./configtool ini config.ini database \"host=127.0.0.1@@port=3306\"")
		fmt.Println("示例2 (多行): ./configtool ini config.ini section \"#注释@@key=value\"")
		os.Exit(1)
	}

	if os.Args[1] != "ini" {
		fmt.Println("第一个参数必须是 'ini'")
		os.Exit(1)
	}

	configPath := os.Args[2]
	if _, err := os.Stat(configPath); os.IsNotExist(err) {
		fmt.Printf("错误: 配置文件 %s 不存在\n", configPath)
		os.Exit(1)
	}

	// 读取原始文件内容
	originalContent, err := os.ReadFile(configPath)
	if err != nil {
		fmt.Printf("读取原始文件失败: %v\n", err)
		os.Exit(1)
	}

	lines := strings.Split(string(originalContent), "\n")
	sectionName := os.Args[3]
	sectionFound := false
	sectionStartLine := -1
	sectionEndLine := -1

	// 查找section
	for i, line := range lines {
		trimmedLine := strings.TrimSpace(line)
		if strings.HasPrefix(trimmedLine, "[") && strings.HasSuffix(trimmedLine, "]") {
			currentSection := trimmedLine[1 : len(trimmedLine)-1]
			if currentSection == sectionName {
				sectionFound = true
				sectionStartLine = i
			} else if sectionStartLine != -1 && sectionEndLine == -1 {
				sectionEndLine = i - 1
				break
			}
		}
	}

	if !sectionFound {
		fmt.Printf("错误: section [%s] 不存在\n", sectionName)
		os.Exit(1)
	}

	if sectionStartLine != -1 && sectionEndLine == -1 {
		sectionEndLine = len(lines) - 1
	}

	// 验证INI格式
	cfg, err := ini.LoadSources(ini.LoadOptions{
		AllowPythonMultilineValues:  true,
		SpaceBeforeInlineComment:    true,
		PreserveSurroundedQuote:     true,
		UnescapeValueCommentSymbols: true,
		IgnoreInlineComment:         false,
		IgnoreContinuation:          true,
	}, configPath)
	if err != nil {
		fmt.Printf("错误: 不是有效的 INI 文件 (%v)\n", err)
		os.Exit(1)
	}

	if cfg.Section(sectionName) == nil {
		fmt.Printf("错误: section [%s] 不存在\n", sectionName)
		os.Exit(1)
	}

	// 增强的entry结构
	type entry struct {
		isComment     bool
		key           string
		value         string
		comment       string
		raw           string
		hasProcessed  bool
		originalLine  string
		originalValue string
	}
	entries := []entry{}

	// 改进的KV对分割逻辑 - 保留原始格式
	kvPairs := strings.Split(os.Args[4], "@@")
	for _, pair := range kvPairs {
		pair = strings.TrimSpace(pair)

		if strings.HasPrefix(pair, "#") || pair == "" {
			entries = append(entries, entry{
				isComment: true,
				raw:       pair,
			})
			continue
		}

		eqIdx := strings.Index(pair, "=")
		if eqIdx <= 0 {
			fmt.Printf("警告: 忽略无效键值对 '%s'\n", pair)
			continue
		}

		key := strings.TrimSpace(pair[:eqIdx])
		rest := pair[eqIdx+1:]

		// 保留原始格式不进行trim
		var value, comment string
		if commentIdx := strings.IndexAny(rest, ";#"); commentIdx >= 0 {
			value = rest[:commentIdx]  // 不trim保留原始空格
			comment = rest[commentIdx:]
		} else {
			value = rest
		}

		entries = append(entries, entry{
			isComment: false,
			key:       key,
			value:     strings.TrimSpace(value), // 仅trim用于比较
			comment:   comment,
			raw:       pair, // 保存原始格式
		})
	}

	// 修改现有键值
	for i := sectionStartLine + 1; i <= sectionEndLine; i++ {
		line := lines[i]
		if eqIdx := strings.Index(line, "="); eqIdx > 0 {
			key := strings.TrimSpace(line[:eqIdx])
			for j := range entries {
				if entries[j].isComment || entries[j].hasProcessed {
					continue
				}

				if entries[j].key == key {
					prefix := line[:eqIdx]
					remaining := line[eqIdx+1:]

					var originalValue, originalComment string
					if commentIdx := strings.IndexAny(remaining, ";#"); commentIdx >= 0 {
						originalValue = remaining[:commentIdx]
						originalComment = remaining[commentIdx:]
					} else {
						originalValue = remaining
					}

					// 记录原始内容
					entries[j].originalLine = strings.TrimSpace(line)
					entries[j].originalValue = strings.TrimSpace(originalValue)
					entries[j].hasProcessed = true

					// 构建新行 - 保留原始格式
					if entries[j].comment != "" {
						lines[i] = prefix + "=" + entries[j].value + entries[j].comment
					} else {
						lines[i] = prefix + "=" + entries[j].value + originalComment
					}

					break
				}
			}
		}
	}

	// 生成要新增的内容
	newLines := []string{}
	for _, entry := range entries {
		if entry.hasProcessed {
			continue
		}
		if entry.isComment {
			newLines = append(newLines, entry.raw)
		} else {
			// 使用raw保留原始格式
			newLines = append(newLines, entry.raw)
		}
	}

	// 插入新内容
	if len(newLines) > 0 {
		insertPos := sectionEndLine + 1
		if insertPos > len(lines) {
			insertPos = len(lines)
		}
		lines = append(lines[:insertPos], append(newLines, lines[insertPos:]...)...)
	}

	// 写入文件
	if err := os.WriteFile(configPath, []byte(strings.Join(lines, "\n")), 0644); err != nil {
		fmt.Printf("错误: 保存配置文件失败 (%v)\n", err)
		os.Exit(1)
	}

	// 增强的输出信息
	fmt.Printf("成功更新配置文件: %s\n", configPath)
	fmt.Printf("修改的section: [%s]\n", sectionName)
	fmt.Println("变更详情:")
	for _, entry := range entries {
		if entry.isComment {
			status := "新增注释"
			if entry.hasProcessed {
				status = "修改注释"
			}
			fmt.Printf("  [%s] %s\n", status, entry.raw)
		} else {
			status := "新增键值"
			if entry.hasProcessed {
				status = fmt.Sprintf("修改键值 (原值: %q)", entry.originalValue)
			}
			fmt.Printf("  [%s] %s\n", status, entry.raw)
		}
	}
}